﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using EPiServer;
using EPiServer.ClientScript;
using EPiServer.ClientScript.Events;
using EPiServer.Configuration;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.Framework.Configuration;
using EPiServer.UI;
using EPiServer.UI.Report;
using EPiServer.UI.WebControls;
using EPiServer.Web.Hosting;
using EPiServer.Web.WebControls;
using log4net;

namespace FilteredPageReference.Pages
{
    public class HyperlinkPropertiesFilteredPageReference : SystemPageBase
    {
        // Fields
        private bool _documentNotFound;
        private bool _documentUnauthorizedAccess;
        private bool _isExternalDocument;
        private bool _isInternalDocument;
        private bool _isInternalUrl;
        private bool _isMailLink;
        private bool _isNetworkDocument;
        private bool _isUnresolvedInternalLink;
        private static readonly ILog _log = LogManager.GetLogger(typeof(HyperlinkPropertiesFilteredPageReference));
        private bool _pageAccessDenied;
        private bool _pageNotFound;
        protected TabStrip actionTab;
        protected HtmlInputHidden activeTab;
        protected ToolButton DeleteButton;
        protected DropDownList documentframe;
        protected Panel DocumentPanel;
        protected Tab DocumentTab;
        protected Panel EmailPanel;
        protected Tab EmailTab;
        protected DropDownList linkframe;
        protected InputPageReference linkinternalurl;
        protected DropDownList linklanguages;
        protected HtmlInputRadioButton linktypeanchor;
        protected HtmlInputRadioButton linktypeexternal;
        protected HtmlInputRadioButton linktypeinternal;
        protected ToolButton OkButton;
        protected const string TabDisabledClass = "epi-tabView-navigation-item-disabled";
        protected Panel tabView;
        protected Panel WebPagePanel;
        protected Tab WebPageTab;

        private PropertyFilteredPageReferenceSettings _settings;

        protected string FPRData
        {
            get
            {
                return Server.UrlDecode(Request.QueryString["fprdata"]).Trim();
            }
        }

        protected string FPRKey
        {
            get
            {
                return Request.QueryString["fprkey"].Trim();
            }
        }

        protected PropertyFilteredPageReferenceSettings FPRSettings
        {
            get
            {
                if (_settings == null)
                    _settings = Helper.GetPropertySettings(FPRData, FPRKey);

                return _settings;
            }
        }


        // Methods
        protected override void OnPreInit(EventArgs e)
        {
            base.OnPreInit(e);
            Page.MasterPageFile = Settings.Instance.UIUrl + "MasterPages/EPiServerUI.Master";
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            base.RegisterClientScriptFile(base.ResolveUrlFromUtil("javascript/common.js"));
            base.Title = LanguageManager.Instance.Translate("/editor/tools/hyperlinkproperties/toolheading");
            if (base.IsPostBack)
            {
                string script = "function CloseAfterPostback(e) {";
                if ((string.Compare(this.activeTab.Value, "0") == 0) && this.linktypeinternal.Checked)
                {
                    UrlBuilder builder = new UrlBuilder(DataFactory.Instance.GetPage(this.linkinternalurl.PageLink).StaticLinkURL);
                    if (this.linklanguages.SelectedIndex > 0)
                    {
                        builder.QueryCollection["epslanguage"] = this.linklanguages.SelectedValue;
                    }
                    script = script + "EPi.GetDialog().returnValue.href = '" + builder.ToString() + "';";
                }
                script = script + "EPi.GetDialog().Close(EPi.GetDialog().returnValue);}";
                this.Page.ClientScript.RegisterClientScriptBlock(base.GetType(), "closeafterpostback", script, true);
                base.ScriptManager.AddEventListener(this.Page, new CustomEvent(EventType.Load, "CloseAfterPostback"));
                return;
            }
            base.ScriptManager.AddEventListener(this.Page, new CustomEvent(EventType.Load, "Initialize"));
            string str = base.Server.UrlDecode(base.Request.QueryString["url"]) ?? string.Empty;
            string str2 = str;
            try
            {
                str2 = StripEnterpriseHostnames(str);
            }
            catch (UriFormatException exception)
            {
                _log.ErrorFormat("Unable to parse url {0}: {1}", str, exception);
            }
            this.IsInternalUrl = str2.StartsWith("/") && (PageReference.ParseUrl(str2) != PageReference.EmptyReference);
            this.IsInternalDocument = (!this.IsInternalUrl && str.StartsWith("/")) || str.StartsWith("~/");
            this.IsNetworkDocument = (str.ToLower().StartsWith("file://") || str.StartsWith(@"\")) || (str.IndexOf(":") == 1);
            this.IsExternalDocument = (base.Request.QueryString["type"] != null) && (string.Compare(base.Request.QueryString["type"], "doc") == 0);
            this.IsMailLink = str.ToLower().StartsWith("mailto:");
            this.IsUnresolvedInternalLink = str.ToLower().StartsWith("~/link/") && (PageReference.ParseUrl(str) == PageReference.EmptyReference);
            if (this.IsInternalUrl)
            {
                Url url = new Url(str);
                if (!string.IsNullOrEmpty(url.QueryCollection["epslanguage"]))
                {
                    this.Language = url.QueryCollection["epslanguage"];
                }
                PageData page = null;
                try
                {
                    page = DataFactory.Instance.GetPage(PageReference.ParseUrl(str));
                }
                catch (PageNotFoundException)
                {
                    this.PageNotFound = true;
                }
                catch (AccessDeniedException)
                {
                    this.PageAccessDenied = true;
                }
                if (page != null)
                {
                    this.linkinternalurl.PageLink = page.PageLink;
                }
            }
            else if (this.IsUnresolvedInternalLink)
            {
                this.PageNotFound = true;
                this.linkinternalurl.PageLink = PageReference.EmptyReference;
            }
            else
            {
                if ((this.IsInternalDocument || this.IsNetworkDocument) || this.IsExternalDocument)
                {
                    this.actionTab.SetSelectedTab(1);
                    if (!this.IsInternalDocument)
                    {
                        goto Label_02B4;
                    }
                    try
                    {
                        this.DocumentNotFound = !(HostingEnvironment.VirtualPathProvider.GetFile(str) is UnifiedFile);
                        goto Label_02B4;
                    }
                    catch (UnauthorizedAccessException)
                    {
                        this.DocumentUnauthorizedAccess = true;
                        goto Label_02B4;
                    }
                }
                if (this.IsMailLink)
                {
                    this.actionTab.SetSelectedTab(2);
                }
            }
        Label_02B4:
            this.PopulateFrameList(this.linkframe);
            this.PopulateFrameList(this.documentframe);
            this.PopulateLanguageList(this.linklanguages);
            this.DataBind();
        }

        private void PopulateFrameList(DropDownList control)
        {
            int num = 1;
            FrameCollection frames = EPiServer.DataAbstraction.Frame.List();
            control.Items.Add(new ListItem(null, null));
            foreach (Frame frame in frames)
            {
                control.Items.Add(new ListItem(frame.LocalizedDescription, frame.Name));
                if (string.Compare(this.Frame, frame.Name, true) == 0)
                {
                    control.SelectedIndex = num;
                }
                num++;
            }
        }

        private void PopulateLanguageList(DropDownList control)
        {
            LanguageBranchCollection branchs = LanguageBranch.ListEnabled();
            control.Items.Add(new ListItem(LanguageManager.Instance.Translate("/editor/tools/hyperlinkproperties/automatically"), string.Empty));
            if (Settings.Instance.UIShowGlobalizationUserInterface)
            {
                foreach (LanguageBranch branch in branchs)
                {
                    ListItem item = new ListItem(branch.Name, branch.LanguageID);
                    item.Selected = base.Request.QueryString["epslanguage"] == branch.LanguageID;
                    control.Items.Add(item);
                }
            }
        }

        internal static string StripEnterpriseHostnames(string url)
        {
            Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
            if ((uri.IsAbsoluteUri && !string.IsNullOrEmpty(uri.AbsolutePath)) && Hostnames.ContainsKey(uri.Host))
            {
                return uri.PathAndQuery;
            }
            return url;
        }

        /// <summary>
        /// Renders the control to the specified HTML writer.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the control content.</param>
        protected override void Render(HtmlTextWriter writer)
        {
            StringBuilder stringBuilder = new StringBuilder();
            using (StringWriter stringWriter = new StringWriter(stringBuilder))
            {
                using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter))
                {
                    base.Render(htmlTextWriter);
                }
            }

            string html = stringBuilder.ToString();
            string pageBrowserUrl = UriSupport.ResolveUrlFromUIBySettings("edit/pagebrowser.aspx");
            int index = html.ToLower().IndexOf(pageBrowserUrl.ToLower());

            if (index != -1)
            {
                html = html.Remove(index, pageBrowserUrl.Length);
                html = html.Insert(index, "/util/FilteredPageReference/PageBrowserFilteredPageReference.aspx?fprkey=" + FPRKey + "&fprdata=" + Server.UrlEncode(FPRData) + "&id=");
            }

            writer.Write(html);
        }

        // Properties
        protected bool DocumentNotFound
        {
            get
            {
                return this._documentNotFound;
            }
            set
            {
                this._documentNotFound = value;
            }
        }

        protected bool DocumentUnauthorizedAccess
        {
            get
            {
                return this._documentUnauthorizedAccess;
            }
            set
            {
                this._documentUnauthorizedAccess = value;
            }
        }

        protected string ErrorMessage
        {
            get
            {
                if (this.IsInternalUrl && this.PageNotFound)
                {
                    return (LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/pagenotfoundmessage") + @"\n\n" + LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/selectnewpagemessage"));
                }
                if (this.IsInternalUrl && this.PageAccessDenied)
                {
                    return (LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/pageaccessdeniedmessage") + @"\n\n" + LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/selectnewpagemessage"));
                }
                if (this.IsInternalDocument && this.DocumentNotFound)
                {
                    return (LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/documentnotfoundmessage") + @"\n\n" + LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/selectnewdocumentmessage"));
                }
                if (this.IsInternalDocument && this.DocumentUnauthorizedAccess)
                {
                    return (LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/documentaccessdeniedmessage") + @"\n\n" + LanguageManager.Instance.TranslateForScript("/editor/tools/hyperlinkproperties/selectnewdocumentmessage"));
                }
                return string.Empty;
            }
        }

        protected string Frame
        {
            get
            {
                return (this.ViewState["_frame"] as string);
            }
            set
            {
                this.ViewState["_frame"] = value;
            }
        }

        private static Dictionary<string, string> Hostnames
        {
            get
            {
                Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
                foreach (EPiServer.Framework.Configuration.HostNameCollection names in EPiServerFrameworkSection.Instance.SiteHostMapping)
                {
                    foreach (EPiServer.Framework.Configuration.HostNameElement element in names)
                    {
                        dictionary.Add(element.Name, element.Name);
                    }
                }
                return dictionary;
            }
        }

        protected bool IsExternalDocument
        {
            get
            {
                return this._isExternalDocument;
            }
            set
            {
                this._isExternalDocument = value;
            }
        }

        protected bool IsInternalDocument
        {
            get
            {
                return this._isInternalDocument;
            }
            set
            {
                this._isInternalDocument = value;
            }
        }

        protected bool IsInternalUrl
        {
            get
            {
                return this._isInternalUrl;
            }
            set
            {
                this._isInternalUrl = value;
            }
        }

        protected bool IsMailLink
        {
            get
            {
                return this._isMailLink;
            }
            set
            {
                this._isMailLink = value;
            }
        }

        protected bool IsNetworkDocument
        {
            get
            {
                return this._isNetworkDocument;
            }
            set
            {
                this._isNetworkDocument = value;
            }
        }

        public bool IsUnresolvedInternalLink
        {
            get
            {
                return this._isUnresolvedInternalLink;
            }
            set
            {
                this._isUnresolvedInternalLink = value;
            }
        }

        protected string Language { get; set; }

        protected bool PageAccessDenied
        {
            get
            {
                return this._pageAccessDenied;
            }
            set
            {
                this._pageAccessDenied = value;
            }
        }

        protected string PageNameFieldId
        {
            get
            {
                if (this.linkinternalurl.DisplayControl == null)
                {
                    return string.Empty;
                }
                return this.linkinternalurl.DisplayControl.ClientID;
            }
        }

        protected bool PageNotFound
        {
            get
            {
                return this._pageNotFound;
            }
            set
            {
                this._pageNotFound = value;
            }
        }

        protected string PageRefFieldId
        {
            get
            {
                if (this.linkinternalurl.ValueControl == null)
                {
                    return string.Empty;
                }
                return this.linkinternalurl.ValueControl.ClientID;
            }
        }

    }
}
 
